package com.evil.application.pojo.dto.form.control.save;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.evil.application.pojo.bo.application.form.control.FormControlBO;
import com.evil.application.pojo.entity.ApplicationForm;
import com.evil.application.pojo.entity.ApplicationFormControl;
import com.evil.application.pojo.entity.FormControlOption;
import com.evil.common.application.enums.form.DefaultValueTypeEnum;
import com.evil.common.core.enums.BaseEnum;
import com.evil.common.family.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * 复制控件 用于实时记录参数 实体
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class CopyControlDTO extends SaveControlDTO {

    private ApplicationForm form;

    /**
     * 收集所有控件选项列表
     */
    private List<FormControlOption> optionList;

    /**
     * 控件id映射map
     */
    private Map<Long, Long> controlIdMap;

    /**
     * 控件映射map
     */
    private Map<Long, ApplicationFormControl> controlMap;

    /**
     * key前端回传控件field；value实际后端入库控件
     */
    private Map<String, ApplicationFormControl> controlFieldMap;

    /**
     * key控件id；value（key前端回传控件选项id（值为负数）；value实际后端入库控件选项id（值为正数））
     */
    private Map<Long, Map<Long, Long>> controlOptionIdMap;

    /**
     * 控件sourceId映射map
     */
    private Map<Long, Long> controlSourceIdMap;

    public CopyControlDTO(ApplicationForm form) {
        this.form = form;
        this.optionList = new ArrayList<>();
        this.controlIdMap = new LinkedHashMap<>();
        this.controlMap = new LinkedHashMap<>();
        this.controlFieldMap = new LinkedHashMap<>();
        this.controlSourceIdMap = new LinkedHashMap<>();
        this.controlOptionIdMap = new LinkedHashMap<>();
    }

    /**
     * 记录控件
     *
     * @param controlBO controlBO
     * @param control   control
     */
    public void putControl(FormControlBO controlBO, ApplicationFormControl control) {
        this.controlIdMap.put(controlBO.getControlId(), control.getControlId());
        this.controlMap.put(controlBO.getControlId(), control);
        this.controlFieldMap.put(controlBO.getControlField(), control);
        this.controlSourceIdMap.put(controlBO.getControlId(), controlBO.getSourceControlId());
    }

    /**
     * 记录控件 新旧映射选项id
     *
     * @param controlId   控件id
     * @param oldOptionId 旧选项id
     * @param newOptionId 新选项id
     */
    public void putControlOptionId(Long controlId, Long oldOptionId, Long newOptionId) {
        Map<Long, Long> optionIdMap = this.getOptionIdMapByControlId(controlId);
        optionIdMap.put(oldOptionId, newOptionId);
        this.controlOptionIdMap.put(controlId, optionIdMap);
    }

    /**
     * 根据field 获取 控件
     *
     * @param controlField controlField
     * @return ApplicationFormControl
     */
    public ApplicationFormControl getControlByField(String controlField) {
        if (!controlFieldMap.containsKey(controlField)) {
            throw new BusinessException(BaseEnum.ERROR_PARAMETER, "控件field不存在");
        }
        return this.controlFieldMap.get(controlField);
    }

    /**
     * 控件 新旧映射选项id
     *
     * @param controlId controlId
     * @return Map
     */
    public Map<Long, Long> getOptionIdMapByControlId(Long controlId) {
        return this.controlOptionIdMap.getOrDefault(controlId, new HashMap<>());
    }

    /**
     * 获取新选项id
     *
     * @param controlId   controlId
     * @param oldOptionId oldOptionId
     * @return Long
     */
    public Long getNewOptionId(Long controlId, Long oldOptionId) {
        Map<Long, Long> optionIdMap = this.getOptionIdMapByControlId(controlId);
        if (!optionIdMap.containsKey(oldOptionId)) {
            throw new BusinessException(BaseEnum.ERROR_PARAMETER, "表格默认数据选项不存在");
        }
        return optionIdMap.get(oldOptionId);
    }

    /**
     * 获取 控件ids
     *
     * @return List
     */
    public List<Long> getControlIds() {
        return controlMap.values().stream().map(ApplicationFormControl::getControlId).collect(Collectors.toList());
    }

    /**
     * 处理 逻辑表单
     *
     * @return List
     */
    public List<FormControlOption> handleLinkControlOptions() {
        List<FormControlOption> options = new ArrayList<>();
        // 遍历optionList，替换
        this.optionList.forEach(option -> {
            List<Long> linkControlIds = JSON.parseArray(option.getLinkControlIds(), Long.class);
            if (CollectionUtil.isNotEmpty(linkControlIds)) {
                // 替换
                linkControlIds = linkControlIds.stream()
                        .filter(this.controlIdMap::containsKey)
                        .map(c -> this.controlIdMap.get(c))
                        .collect(Collectors.toList());
                option.setLinkControlIds(JSON.toJSONString(linkControlIds));
                options.add(option);
            }
        });
        return options;
    }

    /**
     * 替换公式
     *
     * @param replaceFormula 替换公式控件id 方法
     * @return List
     */
    public List<ApplicationFormControl> handleReplaceFormula(BiFunction<String, Map<Long, Long>, Optional<String>> replaceFormula) {
        List<ApplicationFormControl> replaceFormulaControls = new ArrayList<>();
        for (ApplicationFormControl control : this.controlMap.values()) {
            if (control.getDefaultValueType() == DefaultValueTypeEnum.FORMULA_CALCULATION.getId()) {
                // 公式
                replaceFormula.apply(control.getFormula(), this.controlIdMap).ifPresent(formula -> {
                    control.setFormula(formula);
                    replaceFormulaControls.add(control);
                });
            }
        }
        return replaceFormulaControls;
    }
}
